#include "./client.h"
int errnum=0;
int root = 0,root2= 0;
char xbuf[128];
int main(int argc, char const *argv[])
{
	int ret;
	//检验命令行参数个数
	if (3 != argc)
	{
		printf("Usage : %s <IP> <PORT>\n", argv[0]);
		exit(-1);
	}
	// 1. 创建套接字-填充服务器网络信息结构体-connect
	int sockfd = socket_connect(argv);

	MSG msg;
	memset(&msg, 0, sizeof(MSG));
	int n;
	char nn;

	fd_set readfds;    //母本
	FD_ZERO(&readfds); //清空
	fd_set readfds_temp;    //用来备份原集合的
	FD_ZERO(&readfds_temp); //清空
	int max_fd = 0;//记录表中最大的文件描述符
	while (1)
	{
		printf("************************************\n");
		printf("* 1:  登录     2: 退出             *\n");
		printf("************************************\n");
		printf("please choose : ");

		if (scanf("%d", &n) <= 0)
		{
			perror("scanf");
			exit(-1);
		}

		switch (n)
		{
		case 1: 
			//执行登录函数，执行完毕后通过返回值决定是否要跳转到下一个菜单
			if (do_login(sockfd, &msg) == 1)
				goto next;
			break;
		case 2:
			close(sockfd);
			exit(0);
		}
	}
next:
	while (1)
	{
		if (0 == root)
		{
			do_only(sockfd,&msg);
			printf("************************************\n");
			printf("* 1: 查询   2: 修改   3: 退出 *\n");
			printf("************************************\n");
			printf("please choose : ");
			fflush(stdout);
			
			nn=fgetc(stdin);
			//将要监视的文件描述符放到表中
			FD_SET(0, &readfds);
			FD_SET(sockfd, &readfds);
			max_fd = (max_fd > sockfd ? max_fd : sockfd); //记录最大文件描述符
			int ret;
			MSG xxmsg;

			readfds_temp=readfds;
			ret = select(max_fd + 1, &readfds_temp, NULL, NULL,NULL);
			if (ret == -1)
			{
				printf("select error");
			}
			else
			{
				if (FD_ISSET(0, &readfds_temp))
				{
					nn=fgetc(stdin);
				}
				if (FD_ISSET(sockfd, &readfds_temp))
				{
					//接收数据并输出
					if (0 >= recv(sockfd, &xxmsg, sizeof(MSG), 0))
						ERRLOG("send error");
					if (strcmp(xxmsg.data, "在另一台设备登录") == 0)
					{
						printf("%s\n", xxmsg.data);
						exit(0);
					}
				}
			}

			switch (nn)
			{
			case '1': //查询
				do_query(sockfd, &msg);
				break;
			case '2': //修改
				do_Modify(sockfd, &msg);
				break;
			case '3':
				close(sockfd);
				exit(0);
			}
		}
		if (1 == root)
		{	//增、删、改、查
			printf("********************************************************\n");
			printf("* 1: 注册(增)    2: 删除   3: 修改   4: 查询    5: 退出 *\n");
			printf("********************************************************\n");
			printf("please choose : ");

			if (scanf("%d", &n) <= 0)
			{
				perror("scanf");
				exit(-1);
			}

			switch (n)
			{
			case 1: //注册
				do_register(sockfd, &msg);
				break;
			case 2: //删除
				do_delete(sockfd, &msg);
				break;
			case 3://修改
				do_Modify(sockfd, &msg);
				break;
			case 4:
				//查询
				do_query(sockfd, &msg);
				break;
			case 5:
				root=0;
				close(sockfd);
				exit(0);
			}
		}
	}
	//关闭套接字
	close(sockfd);
	return 0;
}

// 1. 创建套接字-填充服务器网络信息结构体-connect
int socket_connect(const char *argv[])
{
	// 1.创建套接字      /IPV4    /TCP
	int sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if (-1 == sockfd)
		ERRLOG("创建套接字 失败");

	// 2.填充服务器网络信息结构体
	struct sockaddr_in server_addr;
	memset(&server_addr, 0, sizeof(server_addr)); //清空
	server_addr.sin_family = AF_INET;			  // IPV4
												  /*端口号   atoi字符串转换成整型数; htons将无符号2字节整型  主机-->网络*/
	server_addr.sin_port = htons(atoi(argv[2]));
	/*ip地址;  inet_addr字符串转换成32位的网络字节序二进制值*/
	server_addr.sin_addr.s_addr = inet_addr(argv[1]);

	//结构体长度
	socklen_t server_addr_len = sizeof(server_addr);

	//与服务器建立连接
	if (-1 == connect(sockfd, (struct sockaddr *)&server_addr, server_addr_len))
	{
		ERRLOG("listen error");
		exit(-1);
	}

	printf("---连接服务器成功---\n");
	return sockfd;
}
// 唯一
void do_only(int sockfd, MSG *msg)
{
	MSG tmsg;
	tmsg.id=msg->id;
	//指定操作码
	tmsg.type =Only;
	//发送数据
	if (0 >= send(sockfd, &tmsg, sizeof(MSG), 0))
		ERRLOG("send error");
	//接收数据
	if (0 >= recv(sockfd, &tmsg, sizeof(MSG), 0))
		ERRLOG("send error");
}

// 1.注册
void do_register(int sockfd, MSG *msg)
{
	memset(msg, 0, sizeof(MSG));
	//指定操作码
	msg->type = R;
	printf("输入ID: ");
	scanf("%d", &msg->id);
	printf("输入[%d] 密码: ", msg->id);
	scanf("%s", msg->pass);
	//发送数据
	if (0 >= send(sockfd, msg, sizeof(MSG), 0))
		ERRLOG("send error");
	//接收数据并输出
	if (0 >= recv(sockfd, msg, sizeof(MSG), 0))
		ERRLOG("send error");

	printf("%s\n", msg->data);
}

// 2.登录
int do_login(int sockfd, MSG *msg)
{
	char NO[32] = "n";
	char unlogin[128]={0};
	printf("是否管理员(y/n): ");
	scanf("%s", NO);
	if (strcmp(NO, "y") == 0 || strcmp(NO, "Y") == 0)
	{
		//指定操作码
		msg->type = ROOT;
		root = 1;
		printf("输入 [%d] 密码: ", msg->id);
		scanf("%s", msg->pass);
		goto root;
	}
	//指定操作码
	msg->type = L;
	root = 0;
	printf("输入ID: ");
	scanf("%d", &msg->id);
	printf("输入 [%d] 密码: ", msg->id);
	scanf("%s", msg->pass);

root:
	//发送数据
	if (0 >= send(sockfd, msg, sizeof(MSG), 0))
		ERRLOG("send error ?");
	//接收数据并输出
	if (0 >= recv(sockfd, msg, sizeof(MSG), 0))
		ERRLOG("recv error");
	printf("%s\n", msg->data);
	sprintf(unlogin,"ID[%d]与密码[%s]不一致", msg->id,msg->pass);
	if (strcmp(msg->data,unlogin)== 0)
	{
		errnum++;
		if (3==errnum)
		{
			errnum=0;
			printf("休息一下,您已经输错3次\n");
			exit(0);
		}
	}
	
	if (strcmp(msg->data, "登录成功") == 0)
	{
		if (1==root)
		{
			memset(msg,0,sizeof(MSG));
		}
		return 1;
	}
	return 0;
}

// 3. 查询
int do_query(int sockfd, MSG *msg)
{
	int id=msg->id;
	memset(msg,0,sizeof(MSG));
	msg->id=id;
	char zoor[64]={0};
	//指定操作码
	msg->type = Q;
	if (1==root&&0==root2)
	{
		printf("输入查询ID{0 all}: ");
		scanf("%d", &msg->id);
		errnum=0;
		if (0==msg->id)
		{
			goto ALLQ;
		}
	}
	//发送数据
	if (0 >= send(sockfd, msg, sizeof(MSG), 0))
		ERRLOG("send error");
	//接收数据并输出
	if (0 >= recv(sockfd, msg, sizeof(MSG), 0))
		ERRLOG("recv error");
	sprintf(zoor,"ID[%d]为空", msg->id);
	if (strcmp(msg->data, zoor) == 0)
	{
		printf("%s\n", msg->data);
	}
	else{
		printf("id     |pass   |name   |sex    |age    |pay    |job    |\n");
		printf("%d\t%s\t%s\t%s\t%d\t%d\t%s\n", msg->id, msg->pass, msg->name, msg->sex, msg->age, msg->pay, msg->job);
		if (0==root2)
		{
			errnum++;
		}
		if (3==errnum)
		{
			errnum=0;
			printf("休息一下,您已经查询3次\n");
			exit(0);
		}
	}
	return 0;
ALLQ:
	All_query(sockfd, msg);
}

// 4. 修改
void do_Modify(int sockfd, MSG *msg)
{
	root2=1;
	if (1==root)
	{
		printf("输入修改ID: ");
		scanf("%d", &msg->id);
	}
	do_query(sockfd,msg);
	char NO[32] = "n";
	int flag=0;
	//指定操作码
	msg->type = M;
	
	printf("开始修改ID: [%d] 信息\n", msg->id);
	// msg->pass,msg->name,msg->sex,msg->age
	// pass='%s',name='%s',sex='%s',age=%d
	printf("修改密码(y/n): ");
	scanf("%s", NO);
	if (strcmp(NO, "y") == 0 || strcmp(NO, "Y") == 0)
	{
		memset(msg->pass, 0, sizeof(msg->pass));
		printf("新密码: ");
		scanf("%s", msg->pass);
		flag=1;
	}
	printf("修改名字(y/n): ");
	scanf("%s", NO);
	if (strcmp(NO, "y") == 0 || strcmp(NO, "Y") == 0)
	{
		memset(msg->name, 0, sizeof(msg->name));
		printf("新名字: ");
		scanf("%s", msg->name);
		flag=1;
	}
	printf("修改性别(y/n): ");
	scanf("%s", NO);
	if (strcmp(NO, "y") == 0 || strcmp(NO, "Y") == 0)
	{
		memset(msg->sex, 0, sizeof(msg->sex));
		printf("新性别: ");
		scanf("%s", msg->sex);
		flag=1;
	}
	printf("修改年龄(y/n): ");
	scanf("%s", NO);
	if (strcmp(NO, "y") == 0 || strcmp(NO, "Y") == 0)
	{
		printf("新年龄: ");
		scanf("%d", &msg->age);
		flag=1;
	}
	if (1==root)
	{
		printf("修改工资(y/n): ");
		scanf("%s", NO);
		if (strcmp(NO, "y") == 0 || strcmp(NO, "Y") == 0)
		{
			printf("新工资: ");
			scanf("%d", &msg->pay);
			flag=1;
		}
		printf("修改职位(y/n): ");
		scanf("%s", NO);
		if (strcmp(NO, "y") == 0 || strcmp(NO, "Y") == 0)
		{
			printf("新职位: ");
			scanf("%s", msg->job);
			flag=1;
		}
	}
	
	if (0==flag)
	{
		printf("无更新\n");
	}
	else
	{
		//发送数据
		if (0 >= send(sockfd, msg, sizeof(MSG), 0))
			ERRLOG("send error");
		//接收数据并输出
		if (0 >= recv(sockfd, msg, sizeof(MSG), 0))
			ERRLOG("recv error");

		if (strcmp(msg->data, "修改成功") == 0)
		{
			printf("%s\n", msg->data);
		}
	}
	root2=0;
}

//删除
void do_delete(int sockfd, MSG *msg)
{
	
	printf("输入删除ID: ");
	scanf("%d", &msg->id);
	//指定操作码
	msg->type = D;
	//发送数据
	if (0 >= send(sockfd, msg, sizeof(MSG), 0))
		ERRLOG("send error");
	//接收数据并输出
	if (0 >= recv(sockfd, msg, sizeof(MSG), 0))
		ERRLOG("recv error");
	printf("%s\n", msg->data);
}

// 7. 查询所有
void All_query(int sockfd, MSG *msg)
{
	memset(msg, 0, sizeof(MSG));
	int flag=0;
	char zoor[64]={0};
	sprintf(zoor,"ID[%d]为空", 0);
	//指定操作码
	msg->type = Qall;
	//发送数据
	if (0 >= send(sockfd, msg, sizeof(MSG), 0))
		ERRLOG("send error");
	while (1)
	{
		//接收数据并输出
		if (0 >= recv(sockfd, msg, sizeof(MSG), 0))
			ERRLOG("recv error");
		if (strcmp(msg->data, zoor) == 0)
		{
			printf("%s\n", msg->data);
		}
		if (strcmp(msg->data,"**over**") == 0)
		{
			printf("输出成功\n");
			break;
		}
		else
		{
			if (0==flag)
			{
				printf("id     |pass   |name   |sex    |age    |pay    |job    |\n");
				flag=1;
			}
			printf("%d\t%s\t%s\t%s\t%d\t%d\t%s\n", msg->id, msg->pass, msg->name, msg->sex, msg->age, msg->pay, msg->job);
			memset(msg, 0, sizeof(MSG));
		}
	}
	flag=0;
}
